home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Libraries / VideoToolbox 94.11.17 / VideoToolboxSources / SndPlay1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-17  |  5.0 KB  |  154 lines  |  [TEXT/KAHL]

  1. /* 
  2. SndPlay1.c
  3.  
  4. SndPlay1(snd) plays a sound, asynchronously, i.e. it returns immediately, while the
  5. sound is still playing. The argument is a handle to a snd resource. If a sound is 
  6. still playing from a previous call to SndPlay1, it is allowed to finish before
  7. closing and reopening the channel and beginning the new sound.
  8. SndPlay1(NULL) waits for the sound to end and then closes the channel.
  9. SndStop1() closes the channel immediately.
  10. SndDone1() returns true once the last sound initiated by SndPlay1() has 
  11. finished.
  12.  
  13. GENERAL NOTE:
  14. The Apple Sound Manager has the annoying characteristic of insisting on loading
  15. any synth that's mentioned in a snd resource, even if that synth is already loaded,
  16. which causes an error. This makes it necessary to dispose of and recreate the 
  17. snd channel before each new sound, which these routines do. Apple advises against 
  18. this approach because it leaves the channel open a lot of the time, 
  19. which blocks SysBeep. 
  20.  
  21. To avoid this, make sure to call SndPlay1(NULL) or SndStop1() to close the channel after
  22. you start a sound going.
  23.  
  24. The easiest way to get a sound to play is to call GetNamedResource(). 
  25.     Handle snd;
  26.     snd=GetNamedResource('snd ',"\pSimple Beep");
  27. However, it's also easy to create your own snd in memory, as a series of commands,
  28. following the instructions in Inside Mac VI.
  29.  
  30. HISTORY:
  31. 3/30/92    dgp wrote it.
  32. 4/1/92    dgp    renamed it and commented out the printf's.
  33. 7/9/93    dgp Test MATLAB in if() instead of #if. 
  34. 5/28/94 dgp Made compatible with Apple's Universal Headers. Thanks to Bob Dougherty 
  35. (wolfgang@cats.ucsc.edu) for reporting the incompatibility.
  36. 9/5/94 dgp removed assumption in printf's that int==short.
  37. 9/10/94 dgp cosmetic
  38. 10/5/94 dgp simplified SndCallBack1 until it stopped crashing when I run native on ppc.
  39. 10/27/94 dgp It is very annoying for the machine to crash anytime you try to quit your application
  40. by escaping via MacsBugs escape to shell. The problem is that CodeWarrior 4.5 doesn't attach
  41. the atexit() tasks to _EscapeToShell. So I do it here. 
  42. */
  43. #include "VideoToolbox.h"
  44. #include <Sound.h>
  45. static pascal void SndCallBack1(SndChannelPtr channel,SndCommand command);
  46. static SndChannelPtr channel=NULL;
  47. static SndCommand callBack;
  48. #if !defined(NewSndCallBackProc)
  49.     #define NewSndCallBackProc (SndCallBackUPP)
  50.     typedef ProcPtr SndCallBackUPP;
  51. #endif
  52. static void PatchExitToShell(void);
  53.  
  54. OSErr SndPlay1(Handle snd)
  55. {
  56.     int error=0;
  57.     
  58.     static firstTime=1;
  59.     static SndCallBackUPP sndCallBackProc;
  60.  
  61.     if(firstTime){
  62.         sndCallBackProc=NewSndCallBackProc(SndCallBack1);
  63.         if(!MATLAB){
  64.             #if __MWERKS__
  65.                 // In CW4.5 _atexit() only gets called if you quit via abort() or exit().
  66.                 PatchExitToShell();
  67.             #else
  68.                 _atexit(SndStop1);
  69.             #endif
  70.         }
  71.         firstTime=0;
  72.     }
  73.     if(channel!=NULL)error=SndDisposeChannel(channel,FALSE);    // wait till done
  74.     channel=NULL;
  75.     if(error)return error;
  76.     if(snd==NULL)return 0;
  77.     error=SndNewChannel(&channel,0,0L,sndCallBackProc);
  78.     if(error){
  79.         printf("%s line %d:SndNewChannel failed with error %d\n",__FILE__,__LINE__,error);
  80.         return error;
  81.     }
  82.     error=SndPlay(channel,snd,TRUE);
  83.     if(error){
  84.         printf("%s line %d:SndPlay failed with error %d\n",__FILE__,__LINE__,error);
  85.         return error;
  86.     }
  87.     callBack.cmd=callBackCmd;
  88.     callBack.param1=0;
  89.     error=SndDoCommand(channel,&callBack,FALSE);
  90.     if(error)printf("%s line %d:SndDoCommand failed with error %d\n",__FILE__,__LINE__,error);
  91.     return error;
  92. }
  93.  
  94. void SndStop1(void)
  95. {
  96.     if(channel!=NULL)SndDisposeChannel(channel,TRUE);        // immediately
  97.     channel=NULL;
  98. }
  99.  
  100. short SndDone1(void)
  101. // Returns 1 if the last sound initiated by SndPlay1 has finished. Otherwise 0.
  102. {
  103.     return callBack.param1;
  104. }
  105.  
  106. #if (THINK_C || THINK_CPLUS)
  107.     #pragma options(!profile)    // Disable profiling because A5 may be invalid.
  108. #endif
  109.  
  110. static pascal void SndCallBack1(SndChannelPtr channel,SndCommand command)
  111. // Load a short int.
  112. // Called back by sound manager.  Lets us know when sound is done.
  113. {
  114.     channel;    // prevent "unused argument" warning
  115.     command.param1=1;
  116. }
  117.  
  118. /*
  119. The following code, which seems to work on 68k and ppc,
  120. is based on examples that appeared in UseNet csmp-digest-v3-046
  121. by Kevin Bell (kbell@cs.utexas.edu) and Bill Hofmann (wdh@netcom.com)
  122. in response to a query by Steve Coy (stevec@jolt.mpx.com.au)
  123. */
  124.  
  125. #if UNIVERSAL_HEADERS
  126.     typedef UniversalProcPtr TrapAddressType;
  127. #else
  128.     #define UniversalProcPtr ProcPtr
  129.     #define NewRoutineDescriptor(a,b,c) a
  130.     typedef long TrapAddressType;
  131. #endif
  132. static UniversalProcPtr oldExitToShellTrapAddress=NULL;
  133. static void PatchExitToShell(void);
  134. static pascal void MyExitToShell(void);
  135. #include <Traps.h>    // _ExitToShell
  136.  
  137. static void PatchExitToShell(void)
  138. {
  139.     UniversalProcPtr myExitToShellUPP;
  140.     if(oldExitToShellTrapAddress==NULL){
  141.         myExitToShellUPP=NewRoutineDescriptor((ProcPtr)MyExitToShell,kPascalStackBased,GetCurrentISA());
  142.         oldExitToShellTrapAddress=(UniversalProcPtr)GetToolTrapAddress(_ExitToShell);
  143.         SetToolTrapAddress((TrapAddressType)myExitToShellUPP,_ExitToShell);
  144.     }
  145. }
  146.  
  147. static pascal void MyExitToShell(void)
  148. {
  149.     SetCurrentA5();
  150.     SetToolTrapAddress((TrapAddressType)oldExitToShellTrapAddress,_ExitToShell);
  151.     SndStop1();
  152.     ExitToShell();
  153. }
  154.